---
title: 'Part 1: Hello'
---

import PlusIcon from '@material-ui/icons/AddSharp'
import FlagIcon from '@material-ui/icons/FlagSharp'
import SaveIcon from '@material-ui/icons/SaveSharp'
import PlayIcon from '@material-ui/icons/PlayArrowSharp'
import StopIcon from '@material-ui/icons/StopSharp'
import SvgHelloPipeline from './hello-pipeline.svg'

**Ahoy, world!**

As programmers, we're all sorta obsessed with _Hello World_, aren't we? So why don't we dive in now and do just that!

## Hello, world!

Type in your terminal the following command:

``` sh
pipy -e "console.log('Hello, world!')"
```

The '-e' option tells Pipy to _evaluate the expression_ coming after. The expression we're evaluating here is:

``` js
console.log('Hello, world!')
```

It says in _PipyJS_, invoke function [console.log()](/reference/api/console/log) with a string parameter _"Hello, world!"_.

> **PipyJS** is the dialect of [ECMAScript](https://en.wikipedia.org/wiki/ECMAScript) that Pipy speaks. Refer to [PipyJS Reference](/reference/pjs) for more information.

Pipy will now start but quit almost immediately, leaving the following output:

```
[INF] Hello, world!
undefined
[ERR] [pjs] Script did not result in a Configuration
[INF] [shutdown] Shutting down...
[INF] [shutdown] Stopped.
Done.
```

Let's take a look at the output:

- On the first line, we see _"Hello, world!"_. This is what the function call to [console.log()](/reference/api/console/log) ended up with: a log output to the console.

- On the second line, we see _"undefined"_. This is the result from _evaluating_ our expression. Since function [console.log()](/reference/api/console/log) has no return values, the evaluated result was _undefined_.

- On the third line, we see an error message saying _"Script did not result in a Configuration"_. Here, [Configuration](/reference/api/Configuration) is the main API provided by Pipy for pipeline setups, which we'll see being used a lot later on. For now, the only thing you need to know is, Pipy requires a _Configuration_ to continue as a long-lived server. However, since the _expression evaluation_ gave us _undefined_, which is not a _Configuration_, so there's nothing else Pipy could do but quit. That's what we see in the output after: Pipy shut down everything and stopped running.

As you can see from above, Pipy is fundamentally an _"expression evaluator"_. If you say _"pipy -e 1+1"_, it tells you _"2"_,  nothing fancy indeed. Surely that isn't what we created Pipy for. To make Pipy do something more interesting, we should write an expression that evaluates to a _Configuration_.

## Hello, world in HTTP!

Now let's use Pipy the way it usually is: run an HTTP server.

``` sh
pipy -e "pipy().listen(8080).serveHTTP(new Message('Hi, there!'))"
```

This time, we're evaluating a slightly more complex expression. The same expression can be rewritten in multiple lines for better clarity:

``` js
pipy()
  .listen(8080)
  .serveHTTP(new Message('Hi, there!'))
```

### Code dissection

Take a bit of time to examine the code. Here's what's going on:

1. At the very first line, the built-in function [pipy()](/reference/api/pipy) is called. It returns a [Configuration](/reference/api/Configuration) object. That's what Pipy expects for running a server.

2. At line 2, by calling method [listen()](/reference/api/Configuration/listen) on the _Configuration_ object that we just got from _pipy()_, we add a _port pipeline layout_ to the configuration that listens on port 8080. Method _listen()_ itself returns the same _Configuration_ object, so we can continually call other methods on it to add more _pipeline layouts_ and _filters_. That's exactly what we are about to do next.

3. At line 3, we add a [serveHTTP()](/reference/classes/Configuration/serveHTTP) filter 
   to the pipeline layout that we just added in line 2. The filter takes a [Message](/reference/classes/Message)
   object as its construction parameter. At runtime, it'll be outputting that same message in
   response to any input messages.

To recap, the expression we've written above defined one _pipeline layout_ containing only one _filter_. To picture it all would be like this:

<div style="text-align: center">
  <SvgHelloPipeline/>
</div>

### Test in action

Input the above command in your terminal, you'll see output like this:

```
[INF] [config]
[INF] [config] Module 
[INF] [config] =======
[INF] [config]
[INF] [config]  [Listen on 8080 at 0.0.0.0]
[INF] [config]  ----->|
[INF] [config]        |
[INF] [config]       serveHTTP -->|
[INF] [config]                    |
[INF] [config]  <-----------------|
[INF] [config]  
[INF] [listener] Listening on TCP port 8080 at 0.0.0.0
```

This time, Pipy didn't quit. Instead, it started listening on port 8080 for HTTP requests.

Now open up a second terminal window and send a request with `curl`:

``` sh
curl localhost:8080
```

You should see the result:

```
Hi, there!
```

## Summary

In this first part of our tutorial, you've learned how a Pipy program is organized by creating and running a simple one-liner HTTP server.

### Takeaways

* A Pipy program is made of definitions of _pipeline layouts_ and _filters_. It always starts off with a call to [pipy()](/reference/api/pipy), which gives us a [Configuration](/reference/api/Configuration) object, which we call various methods on to add _pipeline layouts_ and _filters_.

* A _port pipeline_ reads from a network port and writes back to that port whatever its last filter outputs.

* A [serveHTTP()](/reference/api/Configuration/serveHTTP) filter takes in HTTP messages as requests and outputs HTTP messages as responses.

### What's next?

Now you've made a simple _Hello World_ server, but it's barely useful because it always says the same thing. Next, we'll look at how we can respond to different requests with different responses.
